package logbase

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"
	"sync"
	"time"

	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// 自定义日志级别映射
const (
	SilentLevel = logger.Silent
	ErrorLevel  = logger.Error
	WarnLevel   = logger.Warn
	InfoLevel   = logger.Info
)

// 自定义日志级别文本
var levelTexts = map[logger.LogLevel]string{
	SilentLevel: "SILENT",
	ErrorLevel:  "ERROR",
	WarnLevel:   "WARN",
	InfoLevel:   "INFO",
}

// 定义ANSI颜色常量
const (
	colorReset  = "\033[0m"
	colorRed    = "\033[31m"
	colorGreen  = "\033[32m"
	colorYellow = "\033[33m"
	colorBlue   = "\033[34m"
	colorPurple = "\033[35m"
	colorCyan   = "\033[36m"
	colorWhite  = "\033[37m"
	colorBold   = "\033[1m"
)

// 日志级别对应的颜色
var levelColors = map[logger.LogLevel]string{
	SilentLevel: colorWhite,
	ErrorLevel:  colorRed,
	WarnLevel:   colorYellow,
	InfoLevel:   colorGreen,
}

// MySQLLogger 封装结构体
type MySQLLogger struct {
	Writer                    io.Writer
	LogLevel                  logger.LogLevel
	SlowThreshold             time.Duration
	IgnoreRecordNotFoundError bool
	UseColors                 bool
	mutex                     sync.Mutex // 添加互斥锁确保日志不会交错
}

// NewMySQLLogger 创建新实例
func NewMySQLLogger(configs ...func(*MySQLLogger)) *MySQLLogger {
	l := &MySQLLogger{
		Writer:                    os.Stdout,
		LogLevel:                  InfoLevel,
		SlowThreshold:             200 * time.Millisecond,
		IgnoreRecordNotFoundError: true,
		UseColors:                 true, // 默认启用颜色
	}

	for _, cfg := range configs {
		cfg(l)
	}
	return l
}

// 配置选项
func WithLogLevel(level logger.LogLevel) func(*MySQLLogger) {
	return func(l *MySQLLogger) {
		l.LogLevel = level
	}
}

func WithSlowThreshold(d time.Duration) func(*MySQLLogger) {
	return func(l *MySQLLogger) {
		l.SlowThreshold = d
	}
}

func WithColors(useColors bool) func(*MySQLLogger) {
	return func(l *MySQLLogger) {
		l.UseColors = useColors
	}
}

func WithWriter(writer io.Writer) func(*MySQLLogger) {
	return func(l *MySQLLogger) {
		l.Writer = writer
	}
}

// 实现GORM logger.Interface接口
func (l *MySQLLogger) LogMode(level logger.LogLevel) logger.Interface {
	newLogger := *l
	newLogger.LogLevel = level
	return &newLogger
}

// 格式化日志消息为自定义格式
func (l *MySQLLogger) formatLogMessage(level logger.LogLevel, execTime time.Duration, msg string) string {
	timeStr := time.Now().Format("2006-01-02 15:04:05")
	execTimeStr := execTime.String()
	levelStr := levelTexts[level]

	// 处理SQL消息，使其更加紧凑，避免过长
	if len(msg) > 80 {
		// 如果SQL语句太长，只保留前70个字符，然后添加省略号
		shortMsg := msg[:70] + "..."
		// 但保留尾部的错误信息或行数信息
		if strings.Contains(msg, "[错误:") {
			errorPart := msg[strings.Index(msg, "[错误:"):]
			shortMsg = shortMsg + " " + errorPart
		} else if strings.Contains(msg, "[慢查询") {
			slowPart := msg[strings.Index(msg, "[慢查询"):]
			shortMsg = shortMsg + " " + slowPart
		} else if strings.Contains(msg, "[") && strings.Contains(msg, "行]") {
			rowsPart := msg[strings.LastIndex(msg, "[") : strings.LastIndex(msg, "行]")+3]
			shortMsg = shortMsg + " " + rowsPart
		}
		msg = shortMsg
	}

	if l.UseColors {
		levelColor := levelColors[level]
		return fmt.Sprintf("【%s时间：%s:%s%s%s%s】：%s\n",
			timeStr,
			execTimeStr,
			levelColor,
			colorBold,
			levelStr,
			colorReset,
			msg)
	}

	return fmt.Sprintf("【%s时间：%s:%s】：%s\n", timeStr, execTimeStr, levelStr, msg)
}

// 直接输出格式化的日志到Writer
func (l *MySQLLogger) write(level logger.LogLevel, execTime time.Duration, msg string) {
	if l.LogLevel >= level {
		l.mutex.Lock()
		defer l.mutex.Unlock()

		formattedMsg := l.formatLogMessage(level, execTime, msg)
		fmt.Fprint(l.Writer, formattedMsg)
	}
}

func (l *MySQLLogger) Info(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel >= InfoLevel {
		l.write(InfoLevel, 0, fmt.Sprintf(msg, data...))
	}
}

func (l *MySQLLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel >= WarnLevel {
		l.write(WarnLevel, 0, fmt.Sprintf(msg, data...))
	}
}

func (l *MySQLLogger) Error(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel >= ErrorLevel {
		l.write(ErrorLevel, 0, fmt.Sprintf(msg, data...))
	}
}

func (l *MySQLLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
	if l.LogLevel <= SilentLevel {
		return
	}

	elapsed := time.Since(begin)
	sql, rows := fc()

	// 创建SQL消息
	sqlMessage := sql
	if rows > 0 {
		sqlMessage = fmt.Sprintf("%s [%d行]", sql, rows)
	}

	// 根据不同情况输出不同级别的日志
	switch {
	case err != nil && (!errors.Is(err, gorm.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError):
		l.write(ErrorLevel, elapsed, fmt.Sprintf("%s [错误: %v]", sqlMessage, err))
	case elapsed > l.SlowThreshold && l.SlowThreshold != 0:
		l.write(WarnLevel, elapsed, fmt.Sprintf("%s [慢查询 > %s]", sqlMessage, l.SlowThreshold))
	case l.LogLevel >= InfoLevel:
		l.write(InfoLevel, elapsed, sqlMessage)
	}
}

// 原生SQL驱动日志适配器
type SQLDriverLogger struct {
	Writer    io.Writer
	UseColors bool
	mutex     sync.Mutex // 添加互斥锁确保日志不会交错
}

// NewSQLDriverLogger 创建新的SQL驱动日志适配器
func NewSQLDriverLogger(useColors bool) *SQLDriverLogger {
	return &SQLDriverLogger{
		Writer:    os.Stdout,
		UseColors: useColors,
	}
}

// 格式化驱动日志消息
func (l *SQLDriverLogger) formatDriverMessage(level logger.LogLevel, execTime time.Duration, msg string) string {
	timeStr := time.Now().Format("2006-01-02 15:04:05")
	execTimeStr := execTime.String()
	levelStr := levelTexts[level]

	// 处理SQL消息，使其更加紧凑
	if len(msg) > 80 {
		// 如果消息太长，只保留前70个字符，然后添加省略号
		msg = msg[:70] + "..."
	}

	if l.UseColors {
		levelColor := levelColors[level]
		return fmt.Sprintf("【%s时间：%s:%s%s%s%s】：%s\n",
			timeStr,
			execTimeStr,
			levelColor,
			colorBold,
			levelStr,
			colorReset,
			msg)
	}

	return fmt.Sprintf("【%s时间：%s:%s】：%s\n", timeStr, execTimeStr, levelStr, msg)
}

func (l *SQLDriverLogger) Print(v ...interface{}) {
	// 默认日志级别
	logLevel := InfoLevel
	execTime := time.Duration(0)
	var message string

	// 解析驱动日志格式
	if len(v) > 0 {
		switch v[0] {
		case "sql":
			// SQL执行
			if len(v) >= 6 {
				query := fmt.Sprintf("%v", v[3])
				params := fmt.Sprintf("%v", v[4])

				if t, ok := v[2].(time.Duration); ok {
					execTime = t
				}

				rows := 0
				if r, ok := v[5].(int64); ok {
					rows = int(r)
				}

				if rows > 0 {
					message = fmt.Sprintf("%s [参数: %s] [%d行]", query, params, rows)
				} else {
					message = fmt.Sprintf("%s [参数: %s]", query, params)
				}

				logLevel = InfoLevel
			}
		case "error":
			// 错误信息
			if len(v) >= 2 {
				message = fmt.Sprintf("SQL错误: %v", v[1])
				logLevel = ErrorLevel
			}
		case "connection":
			// 连接事件
			if len(v) >= 2 {
				message = fmt.Sprintf("数据库连接: %v", v[1])
				logLevel = InfoLevel
			}
		default:
			// 其他情况
			message = fmt.Sprintf("%v", v)
		}
	}

	// 格式化并输出日志
	if message != "" {
		l.mutex.Lock()
		defer l.mutex.Unlock()

		formattedMsg := l.formatDriverMessage(logLevel, execTime, message)
		fmt.Fprint(l.Writer, formattedMsg)
	}
}
